import { useEffect, useState } from "react";
import {
  AbstractButton,
  AbstractImage,
  C05CustomerService,
  C06HeroSlideBanner,
  C07MainTitleArea,
  C10TabSection,
  C12Recommendation,
  C13BottomDock,
  Header,
  Icon,
  Layout,
  PriceView,
  WithMargins,
} from "@/components";
import { View } from "@tarojs/components";
import { ApiItemTypeMapping } from "@/data/shared/entityShapes";
import { apiItemTypeMapping } from "@/utils/apiMapping";
import {
  ApiShopItemsMapping,
  ShopConfigurationShape,
  ShopItemShape,
} from "@/data/shop/shopTypes";
import { useAuth } from "@/store/authContext";
import useDetailPageData from "@/hooks/useDetailPageData";
import { useUserInfo } from "@/store/userDataContext";
import { switchTab } from "@/utils/navigation";
import { ActionKeys, ActionNames, sendAction } from "@/utils/tracking";
import { useApplicationInfo } from "@/store/applicationDataContext";
import { useEventListSplit } from "@/hooks/useEventListSplit";
import style from "./index.module.scss";

const eventRecommendationTitleMatch: {
  [key in ApiShopItemsMapping]: string;
} = {
  // publication: "相关推荐",
  [ApiShopItemsMapping.Publication]: "相关推荐",
  [ApiShopItemsMapping.Souvenir]: "相关推荐", // Not in designs but for completeness
  [ApiShopItemsMapping.Giftcertificate]: "活动推荐",
};

const shopRecommendationTitleMatch: {
  [key in ApiShopItemsMapping]: string;
} = {
  [ApiShopItemsMapping.Publication]: "你也可能喜欢",
  [ApiShopItemsMapping.Souvenir]: "相关礼品卡",
  [ApiShopItemsMapping.Giftcertificate]: "相关礼品卡",
};

const ConfigurationSelection = ({
  shopItemData,
  onClose,
  onNextStep,
}: {
  shopItemData: ShopItemShape;
  onClose: () => void;
  onNextStep: (attributeCombinationId: number) => void;
}) => {
  // Initialize empty array of selection
  const [selectedAttr, setSelectedAttr] = useState(
    Array(shopItemData.shopAttrs.length).fill(null)
  );

  const selectedItem = shopItemData.shopValue[selectedAttr.join(",")] as
    | ShopConfigurationShape
    | undefined;
  const imageSource = selectedItem?.image;

  // Disabling, not certain if can return negative numbers
  // Used in two places explicitly to ensure not introducing bugs in case disabled state updated
  const disabled = !selectedItem || selectedItem.stock <= 0;

  return (
    <>
      <View onClick={onClose} className={style["click-intercept"]} />
      <View
        className={style["configuration-wrapper"]}
        onClick={(e) => e.stopPropagation()}
      >
        <Icon type={"CloseBlack"} className={style.close} onClick={onClose} />
        <WithMargins>
          {/* Top display */}
          <View className={style["top-display"]}>
            <AbstractImage
              className={style.image}
              type="none"
              src={imageSource ? imageSource : shopItemData.cover}
            />
            <View className={style["content"]}>
              <View>
                <Header type={"heading-s"}>{shopItemData.name}</Header>
                <View className={style["selection-summary"]}>
                  {shopItemData.shopAttrs
                    .map(
                      (shopAttr, attrIdx) =>
                        `${shopAttr.attrName}: ${
                          selectedAttr[attrIdx]
                            ? selectedAttr[attrIdx]
                            : "请选择"
                        }`
                    )
                    .join("，")}
                </View>
              </View>
              <PriceView
                noSpacing
                price={selectedItem?.price ?? shopItemData.price}
                type="heading-n"
              />
            </View>
          </View>

          {/* Selections */}
          {shopItemData.shopAttrs.map((shopAttr, attrIdx) => (
            <View key={shopAttr.id} className={style["selection-category"]}>
              <View className={style["attribute-name"]}>
                {shopAttr.attrName}
              </View>
              <View className={style["button-container"]}>
                {shopAttr.attrValues.split(",").map((attributeValue) => (
                  <AbstractButton
                    key={attributeValue}
                    color={
                      selectedAttr[attrIdx] === attributeValue
                        ? "viking"
                        : "viking-inactive"
                    }
                    onClick={() => {
                      setSelectedAttr((prev) => {
                        const newSelectedAttr = [...prev];
                        newSelectedAttr[attrIdx] = attributeValue;
                        return newSelectedAttr;
                      });
                    }}
                  >
                    {attributeValue}
                  </AbstractButton>
                ))}
              </View>
            </View>
          ))}
          <AbstractButton
            disabled={disabled}
            color="dark"
            onClick={() => {
              !disabled && onNextStep(selectedItem!.id);
            }}
          >
            提交订单
          </AbstractButton>
        </WithMargins>
      </View>
    </>
  );
};

export default function ShopItemDetail() {
  const { dispatchAuthAction } = useAuth();
  const { dispatch } = useApplicationInfo();
  const [shopItemData, liked, preview] = useDetailPageData<ShopItemShape>(
    "shopitem"
  ) as [ShopItemShape, Boolean, Boolean];
  const [selectedShopAttrData, setSelectedShopAttrData] = useState<
    Array<{
      productId: number;
      count: number;
      attrValueId: number;
    }>
  >([]);

  const [configsExists, setConfigsExists] = useState(false);
  const [configNextStep, setConfigNextStep] = useState<
    null | ((attributeCombinationId: number) => void)>(null);
  const { userData } = useUserInfo().userInfoState;

  useEffect(() => {
    if (shopItemData) {
      dispatch({
        type: "SET_SHARE_DATA",
        data: {
          text: shopItemData.name,
          imagePath: shopItemData.sharePoster
            ? shopItemData.sharePoster
            : shopItemData.cover,
        },
      });
      const filteredSelectedShopAttrData = Object.values(
        shopItemData.shopValue
      ).map((sv) => {
        return {
          productId: shopItemData.shopId,
          count: 1,
          attrValueId: sv.id,
        };
      });
      setSelectedShopAttrData(filteredSelectedShopAttrData);

      setConfigsExists(shopItemData.shopAttrs[0].attrValues !== "default");

      switch (shopItemData.type) {
        case ApiShopItemsMapping.Publication:
          sendAction(ActionNames.PublicationDetailImpression, {
            [ActionKeys.PublicationName]: shopItemData.name,
          });
          break;

        case ApiShopItemsMapping.Giftcertificate:
          sendAction(ActionNames.GiftCardDetailImpression, {
            [ActionKeys.GiftCardName]: shopItemData.name,
            [ActionKeys.GiftCardType]: shopItemData.typeName,
          });
          break;

        case ApiShopItemsMapping.Souvenir:
          sendAction(ActionNames.SouvenirListDetailImpression, {
            [ActionKeys.SouvenirName]: shopItemData.name,
            [ActionKeys.SouvenirType]: shopItemData.typeName,
          });
          break;

        default:
          break;
      }
    }
  }, [shopItemData]);

  const eventRecSplit = useEventListSplit(shopItemData);

  const purchase = async (attributeCombinationId?: number) => {
    if (shopItemData) {
      switch (shopItemData.type) {
        case ApiShopItemsMapping.Publication:
          sendAction(ActionNames.PublicationDetailShopNowClick, {
            [ActionKeys.PublicationName]: shopItemData.name,
            [ActionKeys.PublicationPrice]: shopItemData.price,
          });
          break;

        case ApiShopItemsMapping.Giftcertificate:
          sendAction(ActionNames.GiftCardDetailBuyClick, {
            [ActionKeys.GiftCardName]: shopItemData.name,
            [ActionKeys.GiftCardType]: shopItemData.typeName,
            [ActionKeys.GiftCardAmount]: shopItemData.price,
          });
          break;

        case ApiShopItemsMapping.Souvenir:
          sendAction(ActionNames.SouvenirListDetailBuyClick, {
            [ActionKeys.SouvenirName]: shopItemData.name,
            [ActionKeys.SouvenirType]: shopItemData.typeName,
            [ActionKeys.SouvenirAmount]: shopItemData.price,
          });
          break;

        default:
          break;
      }

      const orderDetailsObj = selectedShopAttrData[0];
      if (attributeCombinationId) {
        orderDetailsObj.attrValueId = attributeCombinationId;
      }
      await shopItemData.handlePlaceOrder({
        query: {
          type: ApiItemTypeMapping.ShopItem,
          orderDetails: [orderDetailsObj],
          preOrderType: "buyNow",
        },
        authDispatch: dispatchAuthAction,
      });
    }
  };

  const addToCart = async (attributeCombinationId?: number) => {
    switch (shopItemData.type) {
      case ApiShopItemsMapping.Publication:
        sendAction(ActionNames.PublicationDetailAddShopClick, {
          [ActionKeys.PublicationName]: shopItemData.name,
          [ActionKeys.PublicationPrice]: shopItemData.price,
        });
        break;

      case ApiShopItemsMapping.Giftcertificate:
        sendAction(ActionNames.GiftCardDetailAddShopClick, {
          [ActionKeys.GiftCardName]: shopItemData.name,
          [ActionKeys.GiftCardType]: shopItemData.typeName,
          [ActionKeys.GiftCardAmount]: shopItemData.price,
        });
        break;

      case ApiShopItemsMapping.Souvenir:
        sendAction(ActionNames.SouvenirListDetailAddShopClick, {
          [ActionKeys.SouvenirName]: shopItemData.name,
          [ActionKeys.SouvenirType]: shopItemData.typeName,
          [ActionKeys.SouvenirAmount]: shopItemData.price,
        });
        break;

      default:
        break;
    }

    await shopItemData.handleAddtoCart({
      query: {
        cartNum: 1,
        productAttrUnique:
          attributeCombinationId ?? selectedShopAttrData[0].attrValueId,
        productId: shopItemData!.shopId,
      },
      method: "POST",
      authDispatch: dispatchAuthAction,
    });
  };

  return (
    <Layout>
      <View className={style.wrapper}>
        {shopItemData && (
          <>
            {!!shopItemData.carouselMap.length && (
              <C06HeroSlideBanner
                images={shopItemData.carouselMap}
                themeColor={shopItemData.typeLabelColor}
                videoSrc={null}
              />
            )}

            <WithMargins>
              <C07MainTitleArea
                categoryName={shopItemData.typeName}
                themeColor={shopItemData.typeLabelColor}
                price={shopItemData.price}
                heading={shopItemData.name}
                description={shopItemData.introduction}
              />
            </WithMargins>

            {/* Tabbed view */}
            <C10TabSection tabContent={shopItemData.tabInfo.details} />

            {!!eventRecSplit.courses.length && (
              <C12Recommendation
                recommendationTitle={
                  eventRecommendationTitleMatch[shopItemData.type]
                }
                cardData={eventRecSplit.courses.map((relatedEvent) => ({
                  cardId: relatedEvent.aboutId,
                  imagePath: relatedEvent.sharePoster || relatedEvent.cover,
                  title: relatedEvent.name,
                  tag: relatedEvent.typeName,
                  cost: relatedEvent.price,
                  type: "course-card",
                  themeColor: relatedEvent.labelColor,
                  redirect: apiItemTypeMapping[relatedEvent.typeCourse],
                }))}
              />
            )}

            {(!!shopItemData.shopRecommendations?.length ||
              !!eventRecSplit.otherEvents.length) && (
              <C12Recommendation
                className={
                  !shopItemData.eventRecommendations
                    ? style["spacing-override"]
                    : null
                }
                recommendationTitle={
                  shopRecommendationTitleMatch[shopItemData.type]
                }
                type="mixed"
                cardData={[
                  ...(shopItemData.shopRecommendations ?? []),
                  ...eventRecSplit.otherEvents,
                ].map((recommendItem) => ({
                  cardId: recommendItem.aboutId,
                  imagePath: recommendItem.sharePoster || recommendItem.cover,
                  title: recommendItem.name,
                  cost: recommendItem.price,
                  type: "recommendation-mixed",
                  themeColor: recommendItem.labelColor,
                  redirect: apiItemTypeMapping[recommendItem.typeCourse],
                }))}
              />
            )}
          </>
        )}
        <C05CustomerService
          cartItemLength={userData?.userInfo.shoppingCartsCount || 0}
          hideCS={true}
          withBottomDock={true}
        />
      </View>
      {shopItemData && !preview && (
        <C13BottomDock
          onPrimaryClick={
            !shopItemData.isDeleted && shopItemData.status
              ? {
                  cb: configsExists
                    ? () => setConfigNextStep(() => purchase)
                    : () => purchase(),
                  disabled: !shopItemData.availability,
                  text: "立即购买",
                }
              : {
                  cb: () => {
                    switchTab("pages/shop/index");
                  },
                  text: "其他商品",
                }
          }
          onSecondaryClick={
            !shopItemData.isDeleted && shopItemData.status
              ? {
                  cb: configsExists
                    ? () => setConfigNextStep(() => addToCart)
                    : () => addToCart(),
                  disabled: !shopItemData.availability,
                  text: "加入购物车",
                }
              : null
          }
          onSaveClick={() => {
            shopItemData.handleFav(
              shopItemData!.shopId,
              ApiItemTypeMapping.ShopItem
            );
          }}
          liked={liked ? true : false}
        />
      )}

      {configNextStep && (
        <ConfigurationSelection
          shopItemData={shopItemData}
          onClose={() => setConfigNextStep(null)}
          onNextStep={configNextStep}
        />
      )}
    </Layout>
  );
}
